/*
 * FLV.h
 *
 *  Created on: Mar 28, 2013
 *      Author: root
 */

#ifndef FLV_H_
#define FLV_H_

#include "StreamBuffer.h"
#include "StreamFormat.h"

/*amf data type enum*/
enum AMFDataType
{
	AMF_NUMBER = 0,
	AMF_BOOLEAN,
	AMF_STRING,
	AMF_OBJECT,
	AMF_MOVIECLIP,		/* reserved, not used */
	AMF_NULL,
	AMF_UNDEFINED,
	AMF_REFERENCE,
	AMF_ECMA_ARRAY,
	AMF_OBJECT_END,
	AMF_STRICT_ARRAY,
	AMF_DATE,
	AMF_LONG_STRING,
	AMF_UNSUPPORTED,
	AMF_RECORDSET,		/* reserved, not used */
	AMF_XML_DOC,
	AMF_TYPED_OBJECT,
	AMF_AVMPLUS,		/* switch to AMF3 */
	AMF_INVALID = 0xff
} ;

/*amf 3 data type enum*/
enum AMF3DataType
{
	AMF3_UNDEFINED = 0,
	AMF3_NULL,
	AMF3_FALSE,
	AMF3_TRUE,
	AMF3_INTEGER,
	AMF3_DOUBLE,
	AMF3_STRING,
	AMF3_XML_DOC,
	AMF3_DATE,
	AMF3_ARRAY,
	AMF3_OBJECT,
	AMF3_XML,
	AMF3_BYTE_ARRAY
} ;

/*var struct define*/
typedef struct AVal
{
	char *av_val;
	unsigned int av_len;
} AVal;

/*afm data struct define*/
struct AMFObjectProperty;

struct AMFObject
{
	int o_num;
	struct AMFObjectProperty *o_props;
};

struct AMFObjectProperty
{
	AVal p_name;
	AMFDataType p_type;
	union
	{
		double p_number;
		AVal p_aval;
		AMFObject p_object;
	} p_vu;
	int16_t p_UTCoffset;
};

/*
 * AMF3ClassDef
 */
struct AMF3ClassDef
{
	AVal cd_name;
	char cd_externalizable;
	char cd_dynamic;
	int cd_num;
	AVal *cd_props;
};

#define AMF3_INTEGER_MAX	268435455
#define AMF3_INTEGER_MIN	-268435456
#define AVMATCH(a1,a2)	((a1)->av_len == (a2)->av_len && !memcmp((a1)->av_val,(a2)->av_val,(a1)->av_len))


/*
 * flv context
 **/
struct FLVContext
{
	AVPacket *header;
	AVPacket *tail;
	uint64_t current_pkt_index;
	uint64_t start_pkt_index;					/*当前流保存位置索引号*/
	u_long   start_uoffset;						/*当前流保存位置的偏移量*/
	uint32_t last_key_frame_timestamp;
	FLVContext()
	{
		this->header = NULL;
		this->tail = this->header;
		this->current_pkt_index = 0;
		start_pkt_index = start_uoffset = 0;
		last_key_frame_timestamp = 0;
	}
};


/**
 * flv class
 */
class FLV
{
public:
	FLV();
	virtual ~FLV();

	static int init_media_info(mediaInfo * pInfo,uint8_t * data,size_t data_len);
	static uint32_t read_flv_time(uint8_t * data,size_t data_len);
	static int	log_fmt(int nloglvl,const char * lpszFormat, ...);

protected:
	/*amf prop set/get*/
	static void AMFProp_GetName(AMFObjectProperty * prop, AVal * name);
	static void AMFProp_SetName(AMFObjectProperty * prop, AVal * name);
	static AMFDataType AMFProp_GetType(AMFObjectProperty * prop);
	static double AMFProp_GetNumber(AMFObjectProperty * prop);
	static int AMFProp_GetBoolean(AMFObjectProperty * prop);
	static void AMFProp_GetString(AMFObjectProperty * prop, AVal * str);
	static void AMFProp_GetObject(AMFObjectProperty * prop, AMFObject * obj);
	static int AMFProp_IsValid(AMFObjectProperty * prop);
	static void AMF_AddProp(AMFObject * obj, const AMFObjectProperty * prop);
	static int AMF_CountProp(AMFObject * obj);
	static void AMFProp_Reset(AMFObjectProperty * prop);
	static void AMFProp_Dump(AMFObjectProperty * prop);
	static AMFObjectProperty * AMF_GetProp(AMFObject * obj, const AVal * name, int nIndex);
	static void AMF_Dump(AMFObject * obj);
	static void AMF_Reset(AMFObject * obj);

	/*amf decode*/
	static uint16_t AMF_DecodeInt8(const char *data);
	static uint16_t AMF_DecodeInt16(const char *data);
	static uint32_t AMF_DecodeInt24(const char *data);
	static uint32_t AMF_DecodeInt32(const char *data);
	static uint64_t AMF_DecodeInt64(const char *data);
	static void AMF_DecodeString(const char *data, AVal * bv);
	static bool AMF_DecodeBoolean(const char *data);
	static double AMF_DecodeNumber(const char *data);
	static int AMF3ReadInteger(const char *data, int32_t * valp);
	static int AMF3ReadString(const char *data, AVal * str);
	static int AMF3_Decode(AMFObject * obj, const char *pBuffer, int nSize, bool bAMFData);
	static int AMF3Prop_Decode(AMFObjectProperty * prop, const char *data, int nSize,int bDecodeName);
	static int AMF_DecodeArray(AMFObject * obj, const char *pBuffer, int nSize,int nArrayLen, bool bDecodeName);
	static int AMFProp_Decode(AMFObjectProperty * prop, const char *pBuffer, int nSize,int bDecodeName);
	static int AMF_Decode(AMFObject * obj, const char *pBuffer, int nSize, bool bDecodeName);

	/*amf encode*/
	static char * AMF_EncodeInt8(char *data,size_t &data_len, char v);
	static char * AMF_EncodeInt16(char *data,size_t &data_len, unsigned int v);
	static char * AMF_EncodeInt24(char *data,size_t &data_len, unsigned int v);
	static char * AMF_EncodeInt32(char *data,size_t &data_len, uint32_t v);
	static char * AMF_EncodeInt64(char *data,size_t &data_len, uint64_t v);
	static char * AMF_EncodeString(char *data,size_t &data_len, const AVal * bv);
	static char * AMF_EncodeNumber(char *data,size_t &data_len, double dVal);
	static char * AMF_EncodeBoolean(char *data,size_t &data_len, bool bVal);
	static char * AMF_EncodeName(char *data,size_t &data_len, const AVal * strName);
	static char * AMF_EncodeNamedString(char *data,size_t &data_len, const AVal * strName, const AVal * strValue);
	static char * AMF_EncodeNamedNumber(char *data,size_t &data_len, const AVal * strName, double dVal);
	static char * AMF_EncodeNamedBoolean(char *data,size_t &data_len, const AVal * strName, bool bVal);
	static char * AMF_Encode(AMFObject * obj, char *data,size_t &data_len);
	static char * AMFProp_Encode(AMFObjectProperty * prop,char *data,size_t &data_len);

	/*AMF3ClassDefinition*/
	static void AMF3CD_AddProp(AMF3ClassDef * cd, AVal * prop);
	static AVal * AMF3CD_GetProp(AMF3ClassDef * cd, int nIndex);
	static int FindFirstMatchingProperty(AMFObject *obj, const AVal *name, AMFObjectProperty * p);
};

#endif /* FLV_H_ */
